#include "timer.h"
#include "io.h"
#include "print.h"
#include "thread.h"
#include "debug.h"

#define IRQ0_FREQUENCY 100 // 频率
#define INPUT_FREQUENCY 1193180 //计数器脉冲频率
#define COUNTER0_VALUE INPUT_FREQUENCY / IRQ0_FREQUENCY // 初值
#define COUNTER0_PORT 0x40 // 计数器0端口号
#define COUNTER0_NO 0 // 选择计数器0
#define COUNTER0_MODE 2 // 计数器工作模式
#define READ_WRITE_LATCH 3 // 读写方式
#define PIT_CONTROL_PORT 0x43 // 控制寄存器端口

uint32_t ticks; //ticks是内核自中断开启以来总共的嘀嗒数

static void frequency_set(uint8_t counter_port, \
                          uint8_t counter_no, \
                          uint8_t rwl, \
                          uint8_t counter_mode, \
                          uint16_t counter_value){
    outb(PIT_CONTROL_PORT, (uint8_t)(counter_no << 6 | rwl << 4 | counter_mode << 1)); //向控制寄存器写入控制字
    outb(counter_port, (uint8_t)counter_value); //写入低8位
    outb(counter_port, (uint8_t)counter_value >> 8); //写入高8位
}

/*时钟的中断处理函数*/
static void intr_timer_handler(void){
    struct task_struct* cur_thread = running_thread();

    ASSERT(cur_thread->stack_magic == 0x19870916); // 检查栈是否溢出

    cur_thread->elapsed_ticks++; // 记录此线程占用的cpu时间
    ticks++; // 从内核第一次处理时间中断后开始至今的嘀嗒数，内核态和用户态的

    if(cur_thread->ticks == 0){ //若进程时间片用完，就开始调度新的进程上cpu
        schedule();
    }else{ // 当前进程时间片-1
        cur_thread->ticks--;
    }
}


void timer_init(void){
    put_str("timer_init start\n");
    frequency_set(  COUNTER0_PORT, \
                    COUNTER0_NO, \
                    READ_WRITE_LATCH, \
                    COUNTER0_MODE, \
                    COUNTER0_VALUE);
    register_handler(0x20, intr_timer_handler);
    put_str("timer_init done\n");
}

